package test

import (
	"codejy/assignmentstrategy"
	"codejy/globalfunc"
	"codejy/store"
	"codejy/structdef"
	"codejy/typedefault"
	"codejy/utils"
	"strings"
)

type Type struct {
	Addr        string
	ThreadStore *structdef.ThreadStore
	TypeName    string
	TypeDef     *structdef.TypeDefinition
}

// 创建实例
func (a *Type) CreateTypeDefault(addr string, threadStore *structdef.ThreadStore, parameter ...string) {
	// 获取类型名称
	var typeName = parameter[0]
	//判断不能是空
	if typeName == "" {
		panic("类型名称不能为空")
	}
	//获取类型的定义
	var typeDef = store.SearchTypeDefinition(threadStore, typeName)
	instance := &Type{
		Addr:        addr,
		ThreadStore: threadStore,
		TypeName:    typeName,
		TypeDef:     typeDef,
	}
	store.AddTypeDefaultInstanceStore(threadStore, a.GetTypeName(), addr, instance)
}
func (a *Type) ParameterProcessing(parameter []string) []string {
	//排除前后""
	for i := range parameter {
		s := parameter[i]
		if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
			s = s[1 : len(s)-1]
			parameter[i] = s
		}
	}
	return parameter
}

func (a *Type) GetData() interface{} {
	return a.TypeName
}

func (a *Type) ToStr() string {
	return ""
}

// 获取类型上的指定注解 ,返回注解的实例地址
func (a *Type) GetTypeLabel(name string) string {
	m := a.TypeDef.Annotations[name]
	//给注解创建实例
	params := assignmentstrategy.CreateInstanceMapNotInitByParams(a.ThreadStore, name, m)
	return params
}

// 获取类型上的所有注解 返回List
func (a *Type) GetTypeLabels() string {
	annotations := a.TypeDef.Annotations
	var list []string
	for k, v := range annotations {
		params := assignmentstrategy.CreateInstanceMapNotInitByParams(a.ThreadStore, k, v)
		list = append(list, params)
	}
	var addrList = globalfunc.ExecuteFunc("SliceToList", list, a.ThreadStore).(string)
	return addrList
}

// 在类型上添加注解或者修改注解
func (a *Type) SetTypeLabel(annotationName string, mapParams string) {

	value, b := typedefault.GetTypeDefaultValue[map[string]string](a.ThreadStore, "Map", mapParams)
	if !b {
		panic("Type->setTypeLabel(1,2): 第二个参数不是Map类型: " + mapParams)
	}
	//获取注解的定义,如果没有定义,那么就创建一个
	a.TypeDef.Annotations[annotationName] = value
}

// 获取指定类型下指定方法的注解
func (a *Type) GetMethodLabel(methodName string, annotationName string) string {
	method := a.TypeDef.Methods[methodName]
	annotation := method.Annotations[annotationName]
	params := assignmentstrategy.CreateInstanceMapNotInitByParams(a.ThreadStore, annotationName, annotation)
	return params
}

// 获取指定类型下指定方法的所有注解
func (a *Type) GetMethodLabels(methodName string) string {
	method := a.TypeDef.Methods[methodName]
	var list []string
	for k, v := range method.Annotations {
		params := assignmentstrategy.CreateInstanceMapNotInitByParams(a.ThreadStore, k, v)
		list = append(list, params)
	}
	var addrList = globalfunc.ExecuteFunc("SliceToList", list, a.ThreadStore).(string)
	return addrList
}

// 在指定类型下的指定方法上添加注解或者修改注解
func (a *Type) SetMethodAnnotation(methodName string, annotationName string, mapParams string) {
	value, b := typedefault.GetTypeDefaultValue[map[string]string](a.ThreadStore, "Map", mapParams)
	if !b {
		panic("Type->setMethodLabel(1,2): 第二个参数不是Map类型:" + mapParams)
	}
	a.TypeDef.Methods[methodName].Annotations[annotationName] = value
}

// 获取类型所有属性名称
func (a *Type) GetFieldsName() string {
	var list []string
	for _, v := range a.TypeDef.Properties {
		list = append(list, v.Name)
	}
	var addrList = globalfunc.ExecuteFunc("SliceToList", list, a.ThreadStore).(string)
	return addrList
}

// 获取类型所有方法名称
func (a *Type) GetMethodsName() string {
	var list []string
	for _, v := range a.TypeDef.Methods {
		list = append(list, v.BehaviorName)
	}
	var addrList = globalfunc.ExecuteFunc("SliceToList", list, a.ThreadStore).(string)
	return addrList
}

// 获取指定方法的方法体,返回字符串
func (a *Type) GetMethodBody(methodName string) string {
	method, p := a.TypeDef.Methods[methodName]
	if !p {
		panic(methodName + "方法不存在,请检查该类型是否存在该方法")
	}
	var methodBody string
	for _, v := range method.Body {
		methodBody += v.LineContent + "\n"
	}
	//去掉最后一个换行符
	methodBody = methodBody[:len(methodBody)-1]
	return methodBody
}

// 添加属性名称
func (a *Type) AddField(name string) {
	properties := a.TypeDef.Properties
	for _, v := range properties {
		if v.Name == name {
			panic(name + "属性已经存在,不能重复添加")
		}
	}
	//添加属性
	var annotations = make(map[string]map[string]string)
	definition := structdef.NewPropertiesDefinition(name,
		-1,
		a.ThreadStore.HandleFilePath, -1, annotations)
	a.TypeDef.Properties = append(properties, definition)
}

// 添加或修改方法 name 方法名称 method 方法体代码
func (a *Type) SetMethodBody(name string, method string) {
	//按行读取字符串
	lines := utils.ReadLine(method)
	codes := structdef.ToLineCode(lines, a.ThreadStore.HandleFilePath)
	//去掉行号,因为行号是在读取文件时添加的,这里添加就乱了
	for i := range codes {
		codes[i].LineNum = -1
	}
	//去除注释和空格,验证赋值变量名称是否合法
	codes = globalfunc.ExecuteFunc("SkipCommentAndEmpty", codes).([]structdef.LineCodeDefinition)
	//匿名函数转换为函数定义
	codes = globalfunc.ExecuteFunc("AnonymousFunctionToFunctionDefine", codes).([]structdef.LineCodeDefinition)
	//优化循环变量声明
	codes = globalfunc.ExecuteFunc("OptimizeForVarDeclare", codes).([]structdef.LineCodeDefinition)

	//添加方法
	var annotations = make(map[string]map[string]string)
	a.TypeDef.Methods[name] = structdef.NewBehaviorDefinition(a.TypeName, name, codes, annotations)
}

// 在方法体最前面添加代码
func (a *Type) AddMethodBeforeCode(name string, codes string) {
	method, p := a.TypeDef.Methods[name]
	if !p {
		panic(name + "方法不存在,请检查该类型是否存在该方法")
	}
	//按行读取字符串
	lines := utils.ReadLine(codes)
	codes1 := structdef.ToLineCode(lines, a.ThreadStore.HandleFilePath)
	//去掉行号,因为行号是在读取文件时添加的,这里添加就乱了
	for i := range codes1 {
		codes1[i].LineNum = -1
	}
	//去除注释和空格,验证赋值变量名称是否合法
	codes1 = globalfunc.ExecuteFunc("SkipCommentAndEmpty", codes1).([]structdef.LineCodeDefinition)
	//匿名函数转换为函数定义
	codes1 = globalfunc.ExecuteFunc("AnonymousFunctionToFunctionDefine", codes1).([]structdef.LineCodeDefinition)
	//优化循环变量声明
	codes1 = globalfunc.ExecuteFunc("OptimizeForVarDeclare", codes1).([]structdef.LineCodeDefinition)
	method.Body = append(codes1, method.Body...)
	a.TypeDef.Methods[name] = method
}

// 在方法体最后面添加代码
func (a *Type) AddMethodAfterCode(name string, codes string) {
	method, p := a.TypeDef.Methods[name]
	if !p {
		panic(name + "方法不存在,请检查该类型是否存在该方法")
	}
	//按行读取字符串
	lines := utils.ReadLine(codes)
	codes1 := structdef.ToLineCode(lines, a.ThreadStore.HandleFilePath)
	//去掉行号,因为行号是在读取文件时添加的,这里添加就乱了
	for i := range codes1 {
		codes1[i].LineNum = -1
	}
	//去除注释和空格,验证赋值变量名称是否合法
	codes1 = globalfunc.ExecuteFunc("SkipCommentAndEmpty", codes1).([]structdef.LineCodeDefinition)
	//匿名函数转换为函数定义
	codes1 = globalfunc.ExecuteFunc("AnonymousFunctionToFunctionDefine", codes1).([]structdef.LineCodeDefinition)
	//优化循环变量声明
	codes1 = globalfunc.ExecuteFunc("OptimizeForVarDeclare", codes1).([]structdef.LineCodeDefinition)
	//定义一个指针
	method.Body = append(method.Body, codes1...)
	a.TypeDef.Methods[name] = method
}

func (f *Type) GetDef() string {
	return `
		@CodeManual(def="new("Type")",des="创建一个类型动态对象")
		type Type{
			def init{
				core&CreateTypeDefault($1)
			}
			@CodeManual(def="getTypeLabel(?)",des="获取类型上的指定名称标签")
			def getTypeLabel{
				to core&GetTypeLabel($1)
			}
			@CodeManual(def="getTypeLabels()",des="获取类型上的所有标签")
			def getTypeLabels{
				to core&GetTypeLabels()
			}
			@CodeManual(def="setTypeLabel(?,?)",des="设置类型上的指定名称标签")
			def setTypeLabel{
				core&SetTypeLabel($1,$2)
			}

			@CodeManual(def="getFieldLabel(?,?)",des="获取类型里面指定名称方法上的指定名称标签")
			def getMethodLabel{
				to core&GetMethodLabel($1,$2)
			}
			@CodeManual(def="getFieldLabels(?)",des="获取类型里面指定名称方法上的所有标签")
			def getMethodLabels{
				to core&GetMethodLabels($1)
			}
			@CodeManual(def="setFieldLabel(?,?,?)",des="设置类型里面指定名称方法上的指定名称标签")
			def setMethodLabel{
				core&SetMethodLabel($1,$2,$3)
			}
			
			@CodeManual(def="getFieldsName()",des="获取类型里面的所有字段名称")
			def getFieldsName{
				to core&GetFieldsName()
			}
			@CodeManual(def="getMethodsName()",des="获取类型里面的所有方法名称")
			def getMethodsName{
				to core&GetMethodsName()
			}
			@CodeManual(def="getMethodBody(?)",des="获取类型里面指定名称方法的方法体")
			def getMethodBody{
				to core&GetMethodBody($1)
			}
			@CodeManual(def="addField(?)",des="在类型里面添加一个字段,如果字段已经存在,则会抛出异常")
			def addField{
				core&AddField($1)
			}
			@CodeManual(def="setMethodBody(?,?)",des="在类型里面添加一个方法,如果方法已经存在,就会覆盖原来的方法")
			def setMethodBody{
				core&SetMethodBody($1,$2)
			}
			@CodeManual(def="addMethodBeforeCode(?,?)",des="在方法体最前面添加代码")
			def addMethodBefore{
				core&AddMethodBeforeCode($1,$2)
			}
			@CodeManual(def="addMethodAfterCode(?,?)",des="在方法体最后面添加代码")
			def addMethodAfter{
				core&AddMethodAfterCode($1,$2)
			}
		}
	`
}
func init() {
	typedefault.RegisterTypeDefault(&Type{})
}

func (f *Type) GetTypeName() string {
	return "Type"
}
